template <class DataType>
ProductionRule<DataType>::ProductionRule()
{
}

template <class DataType>
ProductionRule<DataType>::ProductionRule(DataType lNonTerminal, char rTerminal, DataType rNonTerminal)
{
	leftNonTerminal = lNonTerminal;
	rightTerminal = rTerminal;
	rightNonTerminal = rNonTerminal;
	nonTerminal = true;
}

template <class DataType>
ProductionRule<DataType>::ProductionRule(DataType lNonTerminal, char rTerminal)
{
	leftNonTerminal = lNonTerminal;
	rightTerminal = rTerminal;
	nonTerminal = false;
}

template<class DataType>
ProductionRule<DataType>::ProductionRule(const ProductionRule<DataType> &productionRule)
{
	leftNonTerminal = productionRule.leftNonTerminal;
	rightTerminal = productionRule.rightTerminal;
	rightNonTerminal = productionRule.rightNonTerminal;
	nonTerminal = productionRule.nonTerminal;
}

template <class DataType>
ProductionRule<DataType>::~ProductionRule()
{
}


template <class DataType>
DataType ProductionRule<DataType>::getLeftNonTerminal()
{
	return leftNonTerminal;
}

template <class DataType>
DataType ProductionRule<DataType>::getRightNonTerminal()
{	
	return rightNonTerminal;
}

template <class DataType>
char ProductionRule<DataType>::getRightTerminal()
{
	return rightTerminal;
}

template <class DataType> 
bool ProductionRule<DataType>::getIfEnd(){
	return !nonTerminal;
}

template <class DataType> 
bool ProductionRule<DataType>::operator< (const ProductionRule<DataType> &right) const
{
        if (this->leftNonTerminal < right.leftNonTerminal) {
                return true;
        } else if (this->leftNonTerminal == right.leftNonTerminal) {
        	if (this->nonTerminal && right.nonTerminal) {
        		if (this->rightNonTerminal < right.rightNonTerminal) {
        			return true;
        		} else if (this->rightNonTerminal == right.rightNonTerminal) {
        			return this->rightTerminal < right.rightTerminal;
        		}
        	} else if (this->nonTerminal) {
        		return true;
        	} else if (!right.nonTerminal) {
    			return this->rightTerminal < right.rightTerminal;
        	}
        }
        return false;
}

template <class DataType>
ostream &operator <<(ostream &os, const ProductionRule<DataType> &productionRule)
{
	os << productionRule.leftNonTerminal << "->";
	if(productionRule.rightTerminal == EPSILON)
	{
		os << "Epsilon";
	}
	else 
	{
		os << productionRule.rightTerminal;
	}
	os << productionRule.rightNonTerminal;
	
	return os;
}

template <class DataType> 
bool ProductionRule<DataType>::operator== (const ProductionRule<DataType> &right) const
{
        bool result= false;
        if (leftNonTerminal==right.leftNonTerminal && rightTerminal == right.rightTerminal) {
        	if (nonTerminal && right.nonTerminal) {
        		result = rightNonTerminal==right.rightNonTerminal;
        	} else {
        		result = !nonTerminal && !right.nonTerminal;
        	}
        }        
        return result;
}